/* global util: false */
"use strict";
var Module = (function(util) {
    function Module(ns, name, factory) {
        util.validateName(name);

        var priv = {
            ns: ns,
            name: name,
            factory: factory,
            exported: false
        };

        Object.defineProperty(this, "namespace", {
            value: priv.ns,
            configurable: false,
            writable: false
        });

        Object.defineProperty(this, "ns", {
            value: priv.ns,
            configurable: false,
            writable: false
        });

        Object.defineProperty(this, "name", {
            value: priv.name,
            configurable: false,
            writable: false
        });

        Object.defineProperty(this, "factory", {
            value: priv.factory,
            configurable: false,
            writable: false
        });

        Object.defineProperty(this, "exported", {
            configurable: false,
            get: function() {
                return priv.exported;
            },
            set: function(value) {
                priv.exported = priv.exported || value;
            }
        });
    }

    function doExport(module) {
        var factory = module.factory;
        if (!util.isFunction(factory)) {
            return factory;
        }
        var r = factory.call(module, module);
        return r || module.exports;
    }

    (function(fn) {
        fn.use = function(callback) {
            if (!this.exported) {
                this.exports = doExport(this);
                this.exported = true;
            }

            if (util.isFunction(callback)) {
                callback(this.exports);
            }

            return this.exports;
        };
    })(Module.prototype);

    return Module;
})(util);
